package com.mybatis.jpa.executor;

import com.mybatis.jpa.constants.ParamConstants;
import com.mybatis.jpa.utils.MappedStatementUtils;
import com.mybatis.jpa.utils.ObjectFacade;
import com.mybatis.jpa.utils.StopWatchExt;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 生成insert sql，insert后返回主键给对象
 */
public class PersistentExecutor extends Executor {

	@Override
	public void process(MetaObject metaStatementHandler) throws Exception {

		MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
		//获取入库数据
		Object parameterObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");
		Map<String, Object> parameterMap = (Map<String, Object>) parameterObject;

		ObjectFacade objectFacade = new ObjectFacade(MappedStatementUtils.getEntityClass(mappedStatement));
		//过滤主键，主键的值不能入库。如果主键的值入库会导致数据库（mysql）无法生成新的值，出现锁表
		this.setIdExculde(parameterMap, objectFacade);
		
		MetaObject metaMappedStatement = SystemMetaObject.forObject(mappedStatement);
        //使用批量回写KeyGenerator对象回写ID，mybatis3.3.1之前的版本使用
		//keyProperties赋值，keyProperties主要作用是将数据库生成的主键赋值到对象指定的属性
		metaMappedStatement.setValue("keyProperties", new String[]{objectFacade.getPrimaryKeyField().getFieldName()});

		super.genSql(metaStatementHandler);
	}
	
	/**
	 * 在过滤字段集合里添加主键过滤
	 */
	private void setIdExculde(Map<String, Object> parameterMap, ObjectFacade objectFacade) {
		List<String> exculde = new ArrayList<>();
		if (parameterMap.containsKey(ParamConstants.EXCLUDE_COLUMN)) {
			Object object = parameterMap.get(ParamConstants.EXCLUDE_COLUMN);
			exculde.addAll((List<String>) object);
		}
		exculde.add(objectFacade.getPrimaryKeyColumnName());
		parameterMap.put(ParamConstants.EXCLUDE_COLUMN, exculde);
	}
}
